home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mint99s / biosfs.c < prev    next >
C/C++ Source or Header  |  1992-12-23  |  34KB  |  1,476 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith. All rights reserved.
  3.  */
  4.  
  5. /* simple biosfs.c */
  6.  
  7. #include "mint.h"
  8.  
  9. extern struct kerinfo kernelinfo;    /* see main.c */
  10.  
  11. static long    ARGS_ON_STACK bios_root    P_((int drv, fcookie *fc));
  12. static long    ARGS_ON_STACK bios_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  13. static long    ARGS_ON_STACK bios_getxattr    P_((fcookie *fc, XATTR *xattr));
  14. static long    ARGS_ON_STACK bios_chattr    P_((fcookie *fc, int attrib));
  15. static long    ARGS_ON_STACK bios_chown    P_((fcookie *fc, int uid, int gid));
  16. static long    ARGS_ON_STACK bios_chmode    P_((fcookie *fc, unsigned mode));
  17. static long    ARGS_ON_STACK bios_rmdir    P_((fcookie *dir, const char *name));
  18. static long    ARGS_ON_STACK bios_remove    P_((fcookie *dir, const char *name));
  19. static long    ARGS_ON_STACK bios_getname    P_((fcookie *root, fcookie *dir, char *pathname, int size));
  20. static long    ARGS_ON_STACK bios_rename    P_((fcookie *olddir, char *oldname,
  21.                     fcookie *newdir, const char *newname));
  22. static long    ARGS_ON_STACK bios_opendir    P_((DIR *dirh, int flags));
  23. static long    ARGS_ON_STACK bios_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *fc));
  24. static long    ARGS_ON_STACK bios_rewinddir    P_((DIR *dirh));
  25. static long    ARGS_ON_STACK bios_closedir    P_((DIR *dirh));
  26. static long    ARGS_ON_STACK bios_pathconf    P_((fcookie *dir, int which));
  27. static long    ARGS_ON_STACK bios_dfree    P_((fcookie *dir, long *buf));
  28. static DEVDRV *    ARGS_ON_STACK bios_getdev    P_((fcookie *fc, long *devspecial));
  29. static long    ARGS_ON_STACK bios_fscntl    P_((fcookie *, const char *, int, long));
  30. static long    ARGS_ON_STACK bios_symlink    P_((fcookie *, const char *, const char *));
  31. static long    ARGS_ON_STACK bios_readlink    P_((fcookie *, char *, int));
  32.  
  33. static long    ARGS_ON_STACK bios_topen    P_((FILEPTR *f));
  34. static long    ARGS_ON_STACK bios_twrite    P_((FILEPTR *f, const char *buf, long bytes));
  35. static long    ARGS_ON_STACK bios_tread    P_((FILEPTR *f, char *buf, long bytes));
  36. static long    ARGS_ON_STACK bios_nwrite    P_((FILEPTR *f, const char *buf, long bytes));
  37. static long    ARGS_ON_STACK bios_nread    P_((FILEPTR *f, char *buf, long bytes));
  38. static long    ARGS_ON_STACK bios_ioctl    P_((FILEPTR *f, int mode, void *buf));
  39. static long    ARGS_ON_STACK bios_select    P_((FILEPTR *f, long p, int mode));
  40. static void    ARGS_ON_STACK bios_unselect    P_((FILEPTR *f, long p, int mode));
  41. static long    ARGS_ON_STACK bios_tseek    P_((FILEPTR *f, long where, int whence));
  42.  
  43. long    ARGS_ON_STACK null_open    P_((FILEPTR *f));
  44. long    ARGS_ON_STACK null_write    P_((FILEPTR *f, const char *buf, long bytes));
  45. long    ARGS_ON_STACK null_read    P_((FILEPTR *f, char *buf, long bytes));
  46. long    ARGS_ON_STACK null_lseek    P_((FILEPTR *f, long where, int whence));
  47. long    ARGS_ON_STACK null_ioctl    P_((FILEPTR *f, int mode, void *buf));
  48. long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  49. long    ARGS_ON_STACK null_close    P_((FILEPTR *f, int pid));
  50. long    ARGS_ON_STACK null_select    P_((FILEPTR *f, long p, int mode));
  51. void    ARGS_ON_STACK null_unselect    P_((FILEPTR *f, long p, int mode));
  52.  
  53. static long ARGS_ON_STACK mouse_open    P_((FILEPTR *f));
  54. static long ARGS_ON_STACK mouse_read    P_((FILEPTR *f, char *buf, long nbytes));
  55. static long ARGS_ON_STACK mouse_ioctl P_((FILEPTR *f, int mode, void *buf));
  56. static long ARGS_ON_STACK mouse_close P_((FILEPTR *f, int pid));
  57. static long ARGS_ON_STACK mouse_select P_((FILEPTR *f, long p, int mode));
  58. static void ARGS_ON_STACK mouse_unselect P_((FILEPTR *f, long p, int mode));
  59.  
  60. /* device driver for BIOS terminals */
  61.  
  62. DEVDRV bios_tdevice = {
  63.     bios_topen, bios_twrite, bios_tread, bios_tseek, bios_ioctl,
  64.     null_datime, null_close, bios_select, bios_unselect
  65. };
  66.  
  67. /* device driver for BIOS devices that are not terminals */
  68.  
  69. DEVDRV bios_ndevice = {
  70.     null_open, bios_nwrite, bios_nread, null_lseek, bios_ioctl,
  71.     null_datime, null_close, bios_select, bios_unselect
  72. };
  73.  
  74. DEVDRV null_device = {
  75.     null_open, null_write, null_read, null_lseek, null_ioctl,
  76.     null_datime, null_close, null_select, null_unselect
  77. };
  78.  
  79. DEVDRV mouse_device = {
  80.     mouse_open, null_write, mouse_read, null_lseek, mouse_ioctl,
  81.     null_datime, mouse_close, mouse_select, mouse_unselect
  82. };
  83.  
  84. /* this special driver is checked for in dosfile.c, and indicates that
  85.  * a dup operation is actually wanted rather than an open
  86.  */
  87. DEVDRV fakedev;
  88.  
  89. #ifdef FASTTEXT
  90. extern DEVDRV screen_device;    /* see fasttext.c */
  91. #endif
  92.  
  93. FILESYS bios_filesys = {
  94.     (FILESYS *)0,
  95.     FS_LONGPATH,
  96.     bios_root,
  97.     bios_lookup, nocreat, bios_getdev, bios_getxattr,
  98.     bios_chattr, bios_chown, bios_chmode,
  99.     nomkdir, bios_rmdir, bios_remove, bios_getname, bios_rename,
  100.     bios_opendir, bios_readdir, bios_rewinddir, bios_closedir,
  101.     bios_pathconf, bios_dfree, nowritelabel, noreadlabel,
  102.     bios_symlink, bios_readlink, nohardlink, bios_fscntl, nodskchng
  103. };
  104.  
  105.  
  106. struct tty con_tty, aux_tty, midi_tty;
  107. struct tty sccb_tty, scca_tty, ttmfp_tty;
  108.  
  109. #define BNAME_MAX    13
  110.  
  111. struct bios_file {
  112.     char     name[BNAME_MAX+1];    /* device name */
  113.     DEVDRV *device;            /* device driver for device */
  114.     short    private;        /* extra info for device driver */
  115.     ushort    flags;            /* flags for device open */
  116.     struct tty *tty;        /* tty structure (if appropriate) */
  117.     struct bios_file *next;
  118. };
  119.  
  120. struct bios_file BDEV[] = {
  121.  
  122. /* "real" bios devices present on all machines */
  123.     {"centr", &bios_ndevice, 0, 0, 0, 0},
  124.     {"console", &bios_tdevice, 2, O_TTY, &con_tty, 0},
  125.     {"midi", &bios_tdevice, 3, O_TTY, &midi_tty, 0},
  126.     {"kbd", &bios_ndevice, 4, 0, 0, 0},
  127. /* devices that duplicate handles */
  128.     {"prn", &fakedev, -3, 0, 0, 0}, /* handle -3 (printer) */
  129.     {"aux", &fakedev, -2, 0, 0, 0}, /* handle -2 (aux. terminal) */
  130.     {"con", &fakedev, -1, 0, 0, 0}, /* handle -1 (control terminal) */
  131.     {"tty", &fakedev, -1, 0, 0, 0}, /* the Unix name for it */
  132.     {"stdin", &fakedev, 0, 0, 0, 0},  /* handle 0 (stdin) */
  133.     {"stdout", &fakedev, 1, 0, 0, 0}, /* handle 1 (stdout) */
  134.     {"stderr", &fakedev, 2, 0, 0, 0}, /* handle 2 (stderr) */
  135.  
  136. /* other miscellaneous devices */
  137.     {"mouse", &mouse_device, 0, 0, 0, 0},
  138.     {"null", &null_device, 0, 0, 0, 0},
  139.  
  140. #ifdef FASTTEXT
  141. /* alternate console driver */
  142.     {"fasttext", &screen_device, 2, O_TTY, &con_tty, 0},
  143. #endif
  144.  
  145. /* serial port things *must* come last, because not all of these
  146.  * are present on all machines (except for modem1, which does however
  147.  * have a different device number on TTs and STs)
  148.  */
  149.     {"modem1", &bios_tdevice, 6, O_TTY, &aux_tty, 0},
  150.     {"modem2", &bios_tdevice, 7, O_TTY, &sccb_tty, 0},
  151.     {"serial1", &bios_tdevice, 8, O_TTY, &ttmfp_tty, 0},
  152.     {"serial2", &bios_tdevice, 9, O_TTY, &scca_tty, 0},
  153.     {"", 0, 0, 0, 0, 0}
  154. };
  155.  
  156. struct bios_file *broot, *bdevlast;
  157.  
  158. /* a file pointer for BIOS device 1, provided only for insurance
  159.  * in case a Bconmap happens and we can't allocate a new FILEPTR;
  160.  * in most cases, we'll want to build a FILEPTR in the usual
  161.  * way.
  162.  */
  163.  
  164. FILEPTR *defaultaux;
  165.  
  166. void
  167. biosfs_init()
  168. {
  169.     struct bios_file *b;
  170.  
  171.     broot = BDEV;
  172.  
  173.     for (b = broot; b->name[0]; b++) {
  174.         b->next = b+1;
  175.  
  176.     /* if not a TT or Mega STE, adjust the MODEM1 device to be BIOS
  177.      * device 1
  178.      * and ignore the remaining devices, since they're not present
  179.      */
  180.         if (!has_bconmap && b->private == 6) {
  181.             b->private = 1;
  182.             b->next = 0;
  183.             break;
  184.         }
  185.     /* SERIAL2 is not present on the Mega STe */
  186.         if (mch == MEGASTE && b->private == 8) {
  187.             b->next = 0;
  188.             break;
  189.         }
  190.             
  191.     }
  192.     bdevlast = b;
  193.     if (b->name[0] == 0) {
  194.         --b;
  195.         b->next = 0;
  196.     }
  197.     defaultaux = new_fileptr();
  198.     defaultaux->links = 1;        /* so it never gets freed */
  199.     defaultaux->flags = O_RDWR;
  200.     defaultaux->pos = 0;
  201.     defaultaux->devinfo = 0;
  202.     defaultaux->fc.fs = &bios_filesys;
  203.     defaultaux->fc.index = 0;
  204.     defaultaux->fc.aux = 1;
  205.     defaultaux->fc.dev = BIOSDRV;
  206.     defaultaux->dev = &bios_ndevice;
  207. }
  208.  
  209. static long ARGS_ON_STACK 
  210. bios_root(drv, fc)
  211.     int drv;
  212.     fcookie *fc;
  213. {
  214.     if (drv == BIOSDRV) {
  215.         fc->fs = &bios_filesys;
  216.         fc->dev = drv;
  217.         fc->index = 0L;
  218.         return 0;
  219.     }
  220.     fc->fs = 0;
  221.     return EINTRN;
  222. }
  223.  
  224. static long ARGS_ON_STACK 
  225. bios_lookup(dir, name, fc)
  226.     fcookie *dir;
  227.     const char *name;
  228.     fcookie *fc;
  229. {
  230.     struct bios_file *b;
  231.  
  232.     if (dir->index != 0) {
  233.         DEBUG(("bios_lookup: bad directory"));
  234.         return EPTHNF;
  235.     }
  236. /* special case: an empty name in a directory means that directory */
  237. /* so does "." */
  238.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  239.         *fc = *dir;
  240.         return 0;
  241.     }
  242.  
  243. /* another special case: ".." could be a mount point */
  244.     if (!strcmp(name, "..")) {
  245.         *fc = *dir;
  246.         return EMOUNT;
  247.     }
  248.  
  249.     for (b = broot; b; b = b->next) {
  250.         if (!stricmp(b->name, name)) {
  251.             fc->fs = &bios_filesys;
  252.             fc->index = (long)b;
  253.             fc->aux = b->private;
  254.             fc->dev = dir->dev;
  255.             return 0;
  256.         }
  257.     }
  258.     DEBUG(("bios_lookup: name(%s) not found", name));
  259.     return EFILNF;
  260. }
  261.  
  262. static long ARGS_ON_STACK 
  263. bios_getxattr(fc, xattr)
  264.     fcookie *fc;
  265.     XATTR *xattr;
  266. {
  267.     FILEPTR *f;
  268.     struct bios_file *b = (struct bios_file *)fc->index;
  269.  
  270.     xattr->index = fc->index;
  271.     xattr->dev = fc->dev;
  272.     xattr->nlink = 1;
  273.     xattr->uid = xattr->gid = 0;
  274.     xattr->size = xattr->nblocks = 0;
  275.     xattr->blksize = 1;
  276.     xattr->mtime = xattr->atime = xattr->ctime = timestamp;
  277.     xattr->mdate = xattr->adate = xattr->cdate = datestamp;
  278.     if (fc->index == 0) {        /* root directory? */
  279.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  280.         xattr->attr = FA_DIR;
  281.     } else if (b->device == 0) {    /* symbolic link? */
  282.         xattr->mode = S_IFLNK | DEFAULT_DIRMODE;
  283.     } else if (b->device == &fakedev &&
  284.         (f = curproc->handle[b->private]) != 0)
  285.     {
  286.         /* u:\dev\stdin, u:\dev\stdout, etc. */
  287.         (*f->fc.fs->getxattr) (&f->fc, xattr);
  288.         xattr->index = fc->index;
  289.         xattr->dev = fc->dev;
  290.     } else {
  291.         xattr->mode = S_IFCHR | DEFAULT_MODE;
  292.         xattr->attr = 0;
  293.     }
  294.     return 0;
  295. }
  296.  
  297. static long ARGS_ON_STACK 
  298. bios_chattr(fc, attrib)
  299.     fcookie *fc;
  300.     int attrib;
  301. {
  302.     UNUSED(fc); UNUSED(attrib);
  303.     return EACCDN;
  304. }
  305.  
  306. static long ARGS_ON_STACK 
  307. bios_chown(fc, uid, gid)
  308.     fcookie *fc;
  309.     int uid, gid;
  310. {
  311.     UNUSED(fc); UNUSED(uid);
  312.     UNUSED(gid);
  313.     return EINVFN;
  314. }
  315.  
  316. static long ARGS_ON_STACK 
  317. bios_chmode(fc, mode)
  318.     fcookie *fc;
  319.     unsigned mode;
  320. {
  321.     UNUSED(fc); UNUSED(mode);
  322.     return EINVFN;
  323. }
  324.  
  325. long ARGS_ON_STACK 
  326. nomkdir(dir, name, mode)
  327.     fcookie *dir;
  328.     const char *name;
  329.     unsigned mode;
  330. {
  331.     UNUSED(dir); UNUSED(name);
  332.     UNUSED(mode);
  333.     return EACCDN;
  334. }
  335.  
  336. static long ARGS_ON_STACK 
  337. bios_rmdir(dir, name)
  338.     fcookie *dir;
  339.     const char *name;
  340. {
  341.     return bios_remove(dir, name);
  342. }
  343.  
  344. /*
  345.  * MAJOR BUG: we don't check here for removal of devices for which there
  346.  * are still open files
  347.  */
  348.  
  349. static long ARGS_ON_STACK 
  350. bios_remove(dir, name)
  351.     fcookie *dir;
  352.     const char *name;
  353. {
  354.     struct bios_file *b, **lastb;
  355.  
  356.     UNUSED(dir);
  357.     lastb = &broot;
  358.     for (b = broot; b; b = *(lastb = &b->next)) {
  359.         if (!stricmp(b->name, name)) break;
  360.     }
  361.     if (!b) return EFILNF;
  362.  
  363. /* don't allow removal of the basic system devices */
  364.     if (b >= BDEV && b <= bdevlast) {
  365.         return EACCDN;
  366.     }
  367.     *lastb = b->next;
  368.  
  369.     if (b->device == 0 || b->device == &bios_tdevice)
  370.         kfree(b->tty);
  371.  
  372.     kfree(b);
  373.     return 0;
  374. }
  375.  
  376. static long ARGS_ON_STACK 
  377. bios_getname(root, dir, pathname, size)
  378.     fcookie *root, *dir; char *pathname;
  379.     int size;
  380. {
  381.     char *foo = ((struct bios_file *)dir->index)->name;
  382.  
  383.     UNUSED(root);
  384.     if (dir->index == 0 && size > 0)
  385.         *pathname = 0;
  386.     else if (strlen(foo) < size)
  387.         strcpy(pathname, foo);
  388.     else
  389.         return ERANGE;
  390.     return 0;
  391. }
  392.  
  393. static long ARGS_ON_STACK 
  394. bios_rename(olddir, oldname, newdir, newname)
  395.     fcookie *olddir;
  396.     char *oldname;
  397.     fcookie *newdir;
  398.     const char *newname;
  399. {
  400.     struct bios_file *b;
  401.  
  402.     UNUSED(olddir); UNUSED(newdir);
  403.  
  404. /* BUG: we should check to see if "newname" already exists */
  405.  
  406.     for (b = broot; b; b = b->next) {
  407.         if (!stricmp(b->name, oldname)) {
  408.             strncpy(b->name, newname, BNAME_MAX);
  409.             return 0;
  410.         }
  411.     }
  412.     return EFILNF;
  413. }
  414.  
  415. static long ARGS_ON_STACK 
  416. bios_opendir(dirh, flags)
  417.     DIR *dirh;
  418.     int flags;
  419. {
  420.     UNUSED(flags);
  421.  
  422.     if (dirh->fc.index != 0) {
  423.         DEBUG(("bios_opendir: bad directory"));
  424.         return EPTHNF;
  425.     }
  426.     return 0;
  427. }
  428.  
  429. static long ARGS_ON_STACK 
  430. bios_readdir(dirh, name, namelen, fc)
  431.     DIR *dirh;
  432.     char *name;
  433.     int namelen;
  434.     fcookie *fc;
  435. {
  436.     struct bios_file *b;
  437.     int giveindex = dirh->flags == 0;
  438.     int i;
  439.  
  440.     b = broot;
  441.     i = dirh->index++;
  442.     while(i-- > 0) {
  443.         if (!b) break;
  444.         b = b->next;
  445.     }
  446.     if (!b) {
  447.         return ENMFIL;
  448.     }
  449.     fc->fs = &bios_filesys;
  450.     fc->index = (long)b;
  451.     fc->aux = b->private;
  452.     fc->dev = dirh->fc.dev;
  453.     if (giveindex) {
  454.         namelen -= (int)sizeof(long);
  455.         if (namelen <= 0)
  456.             return ERANGE;
  457.         *((long *)name) = (long) b;
  458.         name += sizeof(long);
  459.     }
  460.     strncpy(name, b->name, namelen-1);
  461.     if (strlen(b->name) >= namelen)
  462.         return ENAMETOOLONG;
  463.     return 0;
  464. }
  465.  
  466. static long ARGS_ON_STACK 
  467. bios_rewinddir(dirh)
  468.     DIR *dirh;
  469. {
  470.     dirh->index = 0;
  471.     return 0;
  472. }
  473.  
  474. static long ARGS_ON_STACK 
  475. bios_closedir(dirh)
  476.     DIR *dirh;
  477. {
  478.     UNUSED(dirh);
  479.     return 0;
  480. }
  481.  
  482. static long ARGS_ON_STACK 
  483. bios_pathconf(dir, which)
  484.     fcookie *dir;
  485.     int which;
  486. {
  487.     UNUSED(dir);
  488.  
  489.     switch(which) {
  490.     case -1:
  491.         return DP_MAXREQ;
  492.     case DP_IOPEN:
  493.         return UNLIMITED;    /* no limit on BIOS file descriptors */
  494.     case DP_MAXLINKS:
  495.         return 1;        /* no hard links available */
  496.     case DP_PATHMAX:
  497.         return PATH_MAX;
  498.     case DP_NAMEMAX:
  499.         return BNAME_MAX;
  500.     case DP_ATOMIC:
  501.         return 1;        /* no atomic writes */
  502.     case DP_TRUNC:
  503.         return DP_AUTOTRUNC;    /* names are truncated */
  504.     case DP_CASE:
  505.         return DP_CASEINSENS;    /* not case sensitive */
  506.     default:
  507.         return EINVFN;
  508.     }
  509. }
  510.  
  511. static long ARGS_ON_STACK 
  512. bios_dfree(dir, buf)
  513.     fcookie *dir;
  514.     long *buf;
  515. {
  516.     UNUSED(dir);
  517.  
  518.     buf[0] = 0;    /* number of free clusters */
  519.     buf[1] = 0;    /* total number of clusters */
  520.     buf[2] = 1;    /* sector size (bytes) */
  521.     buf[3] = 1;    /* cluster size (sectors) */
  522.     return 0;
  523. }
  524.  
  525. /*
  526.  * BIOS Dcntl() calls:
  527.  * Dcntl(0xde02, "U:\DEV\FOO", &foo_descr): install a new device called
  528.  *     "FOO", which is described by the dev_descr structure "foo_descr".
  529.  *     this structure has the following fields:
  530.  *         DEVDRV *driver        the device driver itself
  531.  *       short  dinfo            info for the device driver
  532.  *       short  flags            flags for the file (e.g. O_TTY)
  533.  *       struct tty *tty        tty structure, if appropriate
  534.  *
  535.  * Dcntl(0xde00, "U:\DEV\BAR", n): install a new BIOS terminal device, with
  536.  *     BIOS device number "n".
  537.  * Dcntl(0xde01, "U:\DEV\BAR", n): install a new non-tty BIOS device, with
  538.  *     BIOS device number "n".
  539.  */
  540.  
  541. static long ARGS_ON_STACK 
  542. bios_fscntl(dir, name, cmd, arg)
  543.     fcookie *dir;
  544.     const char *name;
  545.     int cmd;
  546.     long arg;
  547. {
  548.     struct bios_file *b;
  549.  
  550.     UNUSED(dir);
  551.     if ((unsigned)cmd == DEV_INSTALL) {
  552.         struct dev_descr *d = (struct dev_descr *)arg;
  553.  
  554.         b = kmalloc(SIZEOF(struct bios_file));
  555.         if (!b) return 0;
  556.         strncpy(b->name, name, BNAME_MAX);
  557.         b->name[BNAME_MAX] = 0;
  558.         b->device = d->driver;
  559.         b->private = d->dinfo;
  560.         b->flags = d->flags;
  561.         b->tty = d->tty;
  562.         b->next = broot;
  563.         broot = b;
  564.         return (long)&kernelinfo;
  565.     }
  566.     if ((unsigned)cmd == DEV_NEWTTY) {
  567.         b = kmalloc(SIZEOF(struct bios_file));
  568.         if (!b) return ENSMEM;
  569.         b->tty = kmalloc(SIZEOF(struct tty));
  570.         if (!b->tty) {
  571.             kfree(b);
  572.             return ENSMEM;
  573.         }
  574.         strncpy(b->name, name, BNAME_MAX);
  575.         b->name[BNAME_MAX] = 0;
  576.         b->device = &bios_tdevice;
  577.         b->private = arg;
  578.         b->flags = O_TTY;
  579.         *b->tty = default_tty;
  580.         b->next = broot;
  581.         broot = b;
  582.         return 0;
  583.     }
  584.     if ((unsigned)cmd == DEV_NEWBIOS) {
  585.         b = kmalloc(SIZEOF(struct bios_file));
  586.         if (!b) return ENSMEM;
  587.         strncpy(b->name, name, BNAME_MAX);
  588.         b->name[BNAME_MAX] = 0;
  589.         b->tty = 0;
  590.         b->device = &bios_ndevice;
  591.         b->private = arg;
  592.         b->flags = 0;
  593.         b->next = broot;
  594.         return 0;
  595.     }
  596.     return EINVFN;
  597. }
  598.  
  599. static long ARGS_ON_STACK 
  600. bios_symlink(dir, name, to)
  601.     fcookie *dir;
  602.     const char *name, *to;
  603. {
  604.     struct bios_file *b;
  605.     long r;
  606.     fcookie fc;
  607.  
  608.     r = bios_lookup(dir, name, &fc);
  609.     if (r == 0) return EACCDN;    /* file already exists */
  610.     if (r != EFILNF) return r;    /* some other error */
  611.  
  612.     b = kmalloc(SIZEOF(struct bios_file));
  613.     if (!b) return EACCDN;
  614.  
  615.     strncpy(b->name, name, BNAME_MAX);
  616.     b->name[BNAME_MAX] = 0;
  617.     b->device = 0;
  618.     b->private = EINVFN;
  619.     b->flags = 0;
  620.     b->tty = kmalloc((long)strlen(to)+1);
  621.     if (!b->tty) {
  622.         kfree(b);
  623.         return EACCDN;
  624.     }
  625.     strcpy((char *)b->tty, to);
  626.     b->next = broot;
  627.     broot = b;
  628.     return 0;
  629. }
  630.  
  631. static long ARGS_ON_STACK 
  632. bios_readlink(fc, buf, buflen)
  633.     fcookie *fc;
  634.     char *buf;
  635.     int buflen;
  636. {
  637.     struct bios_file *b = (struct bios_file *)fc->index;
  638.  
  639.     if (!b) return EINVFN;
  640.     if (b->device) return EINVFN;
  641.  
  642.     strncpy(buf, (char *)b->tty, buflen);
  643.     if (strlen((char *)b->tty) >= buflen)
  644.         return ENAMETOOLONG;
  645.     return 0;
  646. }
  647.  
  648.  
  649. /*
  650.  * routines for file systems that don't support volume labels
  651.  */
  652.  
  653. long ARGS_ON_STACK 
  654. nowritelabel(dir, name)
  655.     fcookie *dir;
  656.     const char *name;
  657. {
  658.     UNUSED(dir);
  659.     UNUSED(name);
  660.     return EACCDN;
  661. }
  662.  
  663. long ARGS_ON_STACK 
  664. noreadlabel(dir, name, namelen)
  665.     fcookie *dir;
  666.     char *name;
  667.     int namelen;
  668. {
  669.     UNUSED(dir);
  670.     UNUSED(name);
  671.     UNUSED(namelen);
  672.     return EFILNF;
  673. }
  674.  
  675. /*
  676.  * routines for file systems that don't support links
  677.  */
  678.  
  679. long ARGS_ON_STACK 
  680. nosymlink(dir, name, to)
  681.     fcookie *dir;
  682.     const char *name, *to;
  683. {
  684.     UNUSED(dir); UNUSED(name);
  685.     UNUSED(to);
  686.     return EINVFN;
  687. }
  688.  
  689. long ARGS_ON_STACK 
  690. noreadlink(dir, buf, buflen)
  691.     fcookie *dir;
  692.     char *buf;
  693.     int buflen;
  694. {
  695.     UNUSED(dir); UNUSED(buf);
  696.     UNUSED(buflen);
  697.     return EINVFN;
  698. }
  699.  
  700. long ARGS_ON_STACK 
  701. nohardlink(fromdir, fromname, todir, toname)
  702.     fcookie *fromdir, *todir;
  703.     const char *fromname, *toname;
  704. {
  705.     UNUSED(fromdir); UNUSED(todir);
  706.     UNUSED(fromname); UNUSED(toname);
  707.     return EINVFN;
  708. }
  709.  
  710. /* dummy routine for file systems with no Fscntl commands */
  711.  
  712. long ARGS_ON_STACK 
  713. nofscntl(dir, name, cmd, arg)
  714.     fcookie *dir;
  715.     const char *name;
  716.     int cmd;
  717.     long arg;
  718. {
  719.     UNUSED(dir); UNUSED(name);
  720.     UNUSED(cmd); UNUSED(arg);
  721.     return EINVFN;
  722. }
  723.  
  724. /*
  725.  * Did the disk change? Not on this drive!
  726.  * However, we have to do Getbpb anyways, because someone has decided
  727.  * to force a media change on our (non-existent) drive.
  728.  */
  729. long ARGS_ON_STACK 
  730. nodskchng(drv)
  731.     int drv;
  732. {
  733.     (void)getbpb(drv);
  734.     return 0;
  735. }
  736.  
  737. long ARGS_ON_STACK 
  738. nocreat(dir, name, mode, attrib, fc)
  739.     fcookie *dir, *fc;
  740.     const char *name;
  741.     unsigned mode;
  742.     int attrib;
  743. {
  744.     UNUSED(dir); UNUSED(fc);
  745.     UNUSED(name); UNUSED(mode);
  746.     UNUSED(attrib);
  747.     return EACCDN;
  748. }
  749.  
  750. static DEVDRV * ARGS_ON_STACK 
  751. bios_getdev(fc, devsp)
  752.     fcookie *fc;
  753.     long *devsp;
  754. {
  755.     struct bios_file *b;
  756.  
  757.     b = (struct bios_file *)fc->index;
  758.  
  759.     if (b->device && b->device != &fakedev)
  760.         *devsp = (long)b->tty;
  761.     else
  762.         *devsp = b->private;
  763.  
  764.     return b->device;    /* return the device driver */
  765. }
  766.  
  767. /*
  768.  * NULL device driver
  769.  */
  770.  
  771. long ARGS_ON_STACK 
  772. null_open(f)
  773.     FILEPTR *f;
  774. {
  775.     UNUSED(f);
  776.     return 0;
  777. }
  778.  
  779. long ARGS_ON_STACK 
  780. null_write(f, buf, bytes)
  781.     FILEPTR *f; const char *buf; long bytes;
  782. {
  783.     UNUSED(f); UNUSED(buf);
  784.     return bytes;
  785. }
  786.  
  787. long ARGS_ON_STACK 
  788. null_read(f, buf, bytes)
  789.     FILEPTR *f; char *buf; long bytes;
  790. {
  791.     UNUSED(f); UNUSED(buf);
  792.     UNUSED(bytes);
  793.     return 0;
  794. }
  795.  
  796. long ARGS_ON_STACK 
  797. null_lseek(f, where, whence)
  798.     FILEPTR *f; long where; int whence;
  799. {
  800.     UNUSED(f); UNUSED(whence);
  801.     return (where == 0) ? 0 : ERANGE;
  802. }
  803.  
  804. long ARGS_ON_STACK 
  805. null_ioctl(f, mode, buf)
  806.     FILEPTR *f; int mode; void *buf;
  807. {
  808.     UNUSED(f);
  809.     if (mode == FIONREAD) {
  810.         *((long *)buf) = 0;
  811.     }
  812.     else if (mode == FIONWRITE)
  813.         *((long *)buf) = 1;
  814.     else
  815.         return EINVFN;
  816.     return 0;
  817. }
  818.  
  819. long ARGS_ON_STACK 
  820. null_datime(f, timeptr, rwflag)
  821.     FILEPTR *f;
  822.     short *timeptr;
  823.     int rwflag;
  824. {
  825.     UNUSED(f);
  826.     if (rwflag)
  827.         return EACCDN;
  828.     *timeptr++ = timestamp;
  829.     *timeptr = datestamp;
  830.     return 0;
  831. }
  832.  
  833. long ARGS_ON_STACK 
  834. null_close(f, pid)
  835.     FILEPTR *f;
  836.     int pid;
  837. {
  838.     UNUSED(f);
  839.     UNUSED(pid);
  840.     return 0;
  841. }
  842.  
  843. long ARGS_ON_STACK 
  844. null_select(f, p, mode)
  845.     FILEPTR *f; long p;
  846.     int mode;
  847. {
  848.     UNUSED(f); UNUSED(p);
  849.     UNUSED(mode);
  850.     return 1;    /* we're always ready to read/write */
  851. }
  852.  
  853. void ARGS_ON_STACK 
  854. null_unselect(f, p, mode)
  855.     FILEPTR *f;
  856.     long p;
  857.     int mode;
  858. {
  859.     UNUSED(f); UNUSED(p);
  860.     UNUSED(mode);
  861.     /* nothing to do */
  862. }
  863.  
  864. /*
  865.  * BIOS terminal device driver
  866.  */
  867.  
  868. static long ARGS_ON_STACK 
  869. bios_topen(f)
  870.     FILEPTR *f;
  871. {
  872.     f->flags |= O_TTY;
  873.     return 0;
  874. }
  875.  
  876. /*
  877.  * Note: when a BIOS device is a terminal (i.e. has the O_TTY flag
  878.  * set), bios_read and bios_write will only ever be called indirectly, via
  879.  * tty_read and tty_write. That's why we can afford to play a bit fast and
  880.  * loose with the pointers ("buf" is really going to point to a long) and
  881.  * why we know that "bytes" is divisible by 4.
  882.  */
  883.  
  884. static long ARGS_ON_STACK 
  885. bios_twrite(f, buf, bytes)
  886.     FILEPTR *f; const char *buf; long bytes;
  887. {
  888.     long *r;
  889.     long ret = 0;
  890.     int bdev = f->fc.aux;
  891.  
  892.     r = (long *)buf;
  893.     if (f->flags & O_NDELAY) {
  894.         while (bytes > 0) {
  895.             if (!bcostat(bdev)) break;
  896.             if (bconout(bdev, (int)*r) == 0)
  897.             break;
  898.             r++; bytes -= 4; ret+= 4;
  899.         }
  900.     } else {
  901.         while (bytes > 0) {
  902.             if (bconout(bdev, (int)*r) == 0)
  903.             break;
  904.             r++; bytes -= 4; ret+= 4;
  905.         }
  906.     }
  907. #if 0
  908.     (void)checkkeys();
  909. #endif
  910.     return ret;
  911. }
  912.  
  913. static long ARGS_ON_STACK 
  914. bios_tread(f, buf, bytes)
  915.     FILEPTR *f; char *buf; long bytes;
  916. {
  917.     long *r, ret = 0;
  918.     int bdev = f->fc.aux;
  919.  
  920.     r = (long *)buf;
  921.  
  922.     if ((f->flags & O_NDELAY)) {
  923.         while (bytes > 0) {
  924.             if ( !bconstat(bdev) )
  925.             break;
  926.             *r++ = bconin(bdev) & 0x7fffffffL;
  927.             bytes -= 4; ret += 4;
  928.         }
  929.     } else {
  930.         while (bytes > 0) {
  931.             *r++ = bconin(bdev) & 0x7fffffffL;
  932.             bytes -= 4; ret += 4;
  933.         }
  934.     }
  935.     return ret;
  936. }
  937.  
  938. /*
  939.  * read/write routines for BIOS devices that aren't terminals (like the
  940.  * printer & IKBD devices)
  941.  */
  942.  
  943. static long ARGS_ON_STACK 
  944. bios_nwrite(f, buf, bytes)
  945.     FILEPTR *f; const char *buf; long bytes;
  946. {
  947.     long ret = 0;
  948.     int bdev = f->fc.aux;
  949.     int c;
  950.  
  951.     while (bytes > 0) {
  952.         if ( (f->flags & O_NDELAY) && !bcostat(bdev) )
  953.             break;
  954.  
  955.         c = *buf++ & 0x00ff;
  956.  
  957.         if (bconout(bdev, c) == 0)
  958.             break;
  959.  
  960.         bytes--; ret++;
  961.     }
  962.     return ret;
  963. }
  964.  
  965. static long ARGS_ON_STACK 
  966. bios_nread(f, buf, bytes)
  967.     FILEPTR *f; char *buf; long bytes;
  968. {
  969.     long ret = 0;
  970.     int bdev = f->fc.aux;
  971.  
  972.     while (bytes > 0) {
  973.         if ( (f->flags & O_NDELAY) && !bconstat(bdev) )
  974.             break;
  975.         *buf++ = bconin(bdev) & 0xff;
  976.         bytes--; ret++;
  977.     }
  978.     return ret;
  979. }
  980.  
  981. /*
  982.  * BIOS terminal seek code -- this has to match the documented
  983.  * way to do isatty()
  984.  */
  985.  
  986. static long ARGS_ON_STACK 
  987. bios_tseek(f, where, whence)
  988.     FILEPTR *f;
  989.     long where;
  990.     int whence;
  991. {
  992.     UNUSED(f); UNUSED(where);
  993.     UNUSED(whence);
  994. /* terminals always are at position 0 */
  995.     return 0;
  996. }
  997.  
  998. #define MAXBAUD 16
  999.  
  1000. /* keep these sorted in descending order */
  1001. static long baudmap[MAXBAUD] = {
  1002. 19200L, 9600L, 4800L, 3600L, 2400L, 2000L, 1800L, 1200L,
  1003. 600L, 300L, 200L, 150L, 134L, 110L, 75L, 50L
  1004. };
  1005.  
  1006. static long ARGS_ON_STACK 
  1007. bios_ioctl(f, mode, buf)
  1008.     FILEPTR *f; int mode; void *buf;
  1009. {
  1010.     long *r = (long *)buf;
  1011.     struct winsize *ws;
  1012.     char *aline;
  1013.     short dev;
  1014.     int i;
  1015.  
  1016.     if (mode == FIONREAD) {
  1017.         if (bconstat(f->fc.aux))
  1018.             *r = 1;
  1019.         else
  1020.             *r = 0;
  1021.     }
  1022.     else if (mode == FIONWRITE) {
  1023.         if (bcostat(f->fc.aux))
  1024.             *r = 1;
  1025.         else
  1026.             *r = 0;
  1027.     }
  1028.     else if (mode == TIOCFLUSH) {
  1029. /* BUG: this should flush the input/output buffers */
  1030.         return 0;
  1031.     }
  1032.     else if (mode == TIOCGWINSZ && f->fc.aux == 2) {
  1033.         aline = lineA0();
  1034.         ws = (struct winsize *)buf;
  1035.         ws->ws_row = *((short *)(aline - 42)) + 1;
  1036.         ws->ws_col = *((short *)(aline - 44)) + 1;
  1037.     } else if (mode == TIOCIBAUD || mode == TIOCOBAUD) {
  1038.         long oldbaud, newbaud;
  1039.         dev = f->fc.aux;
  1040.  
  1041.         newbaud = *r;
  1042.         if (dev == 1 || dev >= 6) {
  1043.             if (has_bconmap)
  1044.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1045.             i = (int)rsconf(-2, -1, -1, -1, -1, -1);
  1046.             if (i < 0 || i >= MAXBAUD)
  1047.                 oldbaud = -1L;
  1048.             else
  1049.                 oldbaud = baudmap[i];
  1050.             *r = oldbaud;
  1051.             if (newbaud > 0) {
  1052.     /* BUG: assert DTR works only on modem1 */
  1053.                 if (dev == 1 || dev == 6) {
  1054.                     Offgibit(0xef);
  1055.                 }
  1056.                 for (i = 0; i < MAXBAUD; i++) {
  1057.                     if (baudmap[i] == newbaud) {
  1058.                         rsconf(i, -1, -1, -1, -1, -1);
  1059.                         return 0;
  1060.                     } else if (baudmap[i] < newbaud) {
  1061.                         *r = baudmap[i];
  1062.                         break;
  1063.                     }
  1064.                 }
  1065.                 return ERANGE;
  1066.             } else if (newbaud == 0L) {
  1067.     /* BUG: drop DTR: works only on modem1 */
  1068.                 if (dev == 1 || dev == 6) {
  1069.                     Ongibit(0x10);
  1070.                 }
  1071.             }
  1072.             return 0;
  1073.         } else if (dev == 2 || dev == 5) {
  1074.             /* screen: assume 9600 baud */
  1075.             oldbaud = 9600L;
  1076.         } else if (dev == 3) {
  1077.             /* midi */
  1078.             oldbaud = 31250L;
  1079.         } else {
  1080.             oldbaud = -1L;    /* unknown speed */
  1081.         }
  1082.         *r = oldbaud;
  1083.         if (newbaud > 0 && newbaud != oldbaud)
  1084.             return ERANGE;
  1085.         return 0;
  1086.     } else if (mode == TIOCCBRK || mode == TIOCSBRK) {
  1087.         unsigned long bits;
  1088.  
  1089.         dev = f->fc.aux;
  1090.         if (dev == 1 || dev >= 6) {
  1091.             if (has_bconmap)
  1092.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1093.         } else {
  1094.             return EINVFN;
  1095.         }
  1096.         bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1097.         bits = (bits >> 8) & 0x0ff;        /* isolate TSR byte */
  1098.         if (mode == TIOCCBRK)
  1099.             bits &= ~8;
  1100.         else
  1101.             bits |= 8;
  1102.         (void)rsconf(-1, -1, -1, -1, (int)bits, -1);
  1103.     } else if (mode == TIOCGFLAGS || mode == TIOCSFLAGS) {
  1104.         unsigned short oflags, flags;
  1105.         unsigned long bits;
  1106.         unsigned char ucr;
  1107.         short flow;
  1108.  
  1109.         dev = f->fc.aux;
  1110.         if (dev == 1 || dev >= 6) {
  1111.             oflags = ((struct tty *)f->devinfo)->sg.sg_flags;
  1112.             oflags &= (T_TANDEM|T_RTSCTS);
  1113.             if (has_bconmap)
  1114.                 mapin((dev == 1) ? curproc->bconmap : dev);
  1115.             bits = rsconf(-1, -1, -1, -1, -1, -1);    /* get settings */
  1116.             ucr = (bits >> 24L) & 0x0ff;        /* isolate UCR byte */
  1117.             oflags |= (ucr >> 3) & (TF_STOPBITS|TF_CHARBITS);
  1118.             if (ucr & 0x4) {            /* parity on? */
  1119.                 oflags |= (ucr & 0x2) ? T_EVENP : T_ODDP;
  1120.             }
  1121.             if (mode == TIOCSFLAGS) {
  1122.                 flags = (*(unsigned short *)buf);
  1123.                 if (flags & T_EVENP) {
  1124.                     ucr |= 0x6;
  1125.                 } else if (flags & T_ODDP) {
  1126.                     ucr &= ~2;
  1127.                     ucr |= 0x4;
  1128.                 } else {
  1129.                     ucr &= ~6;
  1130.                 }
  1131.                 if (flags & TF_STOPBITS) {
  1132.                     ucr &= ~(0x18);
  1133.                     ucr |= (flags & TF_STOPBITS) << 3;
  1134.                 }
  1135.                 ucr &= ~(0x60);
  1136.                 ucr |= (flags & TF_CHARBITS) << 3;
  1137.                 flow = (flags & (T_RTSCTS|T_TANDEM)) >> 12L;
  1138.                 rsconf(-1, flow, ucr, -1, -1, -1);
  1139.             } else {
  1140.                 *((unsigned short *)buf) = oflags;
  1141.             }
  1142.         } else {
  1143.             return EINVFN;
  1144.         }
  1145.     } else if ((mode >= TCURSOFF && mode <= TCURSGRATE) && (f->fc.aux == 2)) {
  1146.         return Cursconf(mode - TCURSOFF, *((short *)buf));
  1147.     } else {
  1148.     /* Fcntl will automatically call tty_ioctl to handle
  1149.      * terminal calls that we didn't deal with
  1150.      */
  1151.         return EINVFN;
  1152.     }
  1153.     return 0;
  1154. }
  1155.  
  1156. static long ARGS_ON_STACK 
  1157. bios_select(f, p, mode)
  1158.     FILEPTR *f; long p; int mode;
  1159. {
  1160.     struct tty *tty = (struct tty *)f->devinfo;
  1161.     int dev = f->fc.aux;
  1162.  
  1163.     if (mode == O_RDONLY) {
  1164.         if (bconstat(dev)) {
  1165.             TRACE(("bios_select: data present for device %d", dev));
  1166.             return 1;
  1167.         }
  1168.         if (tty) {
  1169.         /* avoid collisions with other processes */
  1170.             if (!tty->rsel)
  1171.                 tty->rsel = p;
  1172.         }
  1173.         return 0;
  1174.     } else if (mode == O_WRONLY) {
  1175.         if (bcostat(dev)) {
  1176.             TRACE(("bios_select: ready to output on %d", dev));
  1177.             return 1;
  1178.         }
  1179.         if (tty) {
  1180.             if (!tty->wsel)
  1181.                 tty->wsel = p;
  1182.         }
  1183.         return 0;
  1184.     }
  1185.     /* default -- we don't know this mode, return 0 */
  1186.     return 0;
  1187. }
  1188.  
  1189. static void ARGS_ON_STACK 
  1190. bios_unselect(f, p, mode)
  1191.     FILEPTR *f;
  1192.     long p;
  1193.     int mode;
  1194. {
  1195.     struct tty *tty = (struct tty *)f->devinfo;
  1196.  
  1197.     if (tty) {
  1198.         if (mode == O_RDONLY && tty->rsel == p)
  1199.             tty->rsel = 0;
  1200.         else if (mode == O_WRONLY && tty->wsel == p)
  1201.             tty->wsel = 0;
  1202.     }
  1203. }
  1204.  
  1205. /*
  1206.  * mouse device driver
  1207.  */
  1208.  
  1209. #define MOUSESIZ 128*3
  1210. static unsigned char mousebuf[MOUSESIZ];
  1211. static int mousehead, mousetail;
  1212.  
  1213. long mousersel;    /* is someone calling select() on the mouse? */
  1214.  
  1215. char mshift;        /* shift key status; set by checkkeys() in bios.c */
  1216. short *gcurx = 0,
  1217.       *gcury = 0;    /* mouse pos. variables; used by big screen emulators */
  1218.  
  1219. void ARGS_ON_STACK 
  1220. mouse_handler(buf)
  1221.     const char *buf;    /* must be a *signed* character */
  1222. {
  1223.     unsigned char *mbuf, buttons;
  1224.     int newmtail;
  1225.     short dx, dy;
  1226.  
  1227. /* the Sun mouse driver has 0=down, 1=up, while the atari hardware gives
  1228.    us the reverse. also, we have the "middle" button and the "left"
  1229.    button reversed; so we use this table to convert (and also to add the
  1230.    0x80 to indicate a mouse packet)
  1231.  */
  1232.     static int _cnvrt[8] = {
  1233.         0x87, 0x86, 0x83, 0x82, 0x85, 0x84, 0x81, 0x80
  1234.     };
  1235.  
  1236.     mbuf = &mousebuf[mousetail];
  1237.     newmtail = mousetail + 3;
  1238.     if (newmtail >= MOUSESIZ)
  1239.         newmtail = 0;
  1240.     if (newmtail == mousehead)
  1241.         return;            /* buffer full */
  1242.  
  1243.     buttons = *buf++ & 0x7;        /* convert to SUN format */
  1244.     if (mshift & 0x3) {        /* a shift key held down? */
  1245.     /* if so, convert shift+button to a "middle" button */
  1246.         if (buttons == 0x1 || buttons == 0x2)
  1247.             buttons = 0x4;
  1248.         else if (buttons == 0x3)
  1249.             buttons = 0x7;
  1250.     }
  1251.     *mbuf++ = _cnvrt[buttons];    /* convert to Sun format */
  1252.     dx = *buf++;
  1253.     *mbuf++ = dx;            /* copy X delta */
  1254.     dy = *buf;
  1255.     *mbuf = -dy;            /* invert Y delta for Sun format */
  1256.     mousetail = newmtail;
  1257.     *gcurx += dx;            /* update line A variables */
  1258.     *gcury += dy;
  1259. /*
  1260.  * if someone has called select() waiting for mouse input, wake them
  1261.  * up
  1262.  */
  1263.     if (mousersel) {
  1264.         wakeselect(mousersel);
  1265.     }
  1266. }
  1267.  
  1268. extern void newmvec(), newjvec();    /* in intr.s */
  1269. static long oldvec = 0;
  1270. long oldjvec = 0;
  1271.  
  1272. static long ARGS_ON_STACK 
  1273. mouse_open(f)
  1274.     FILEPTR *f;
  1275. {
  1276.     char *aline;
  1277.  
  1278.     static char parameters[] = {
  1279.         0,         /* Y=0 in lower corner */
  1280.         0,        /* normal button handling */
  1281.         1, 1        /* X, Y scaling factors */
  1282.     };
  1283.  
  1284.     UNUSED(f);
  1285.  
  1286.     if (oldvec)        /* mouse in use */
  1287.         return EACCDN;
  1288.  
  1289. /* initialize pointers to line A variables */
  1290.     if (!gcurx) {
  1291.         aline = lineA0();
  1292.         if (aline == 0)    {    /* should never happen */
  1293.             ALERT("unable to read line A variables");
  1294.             return -1;
  1295.         }
  1296.         gcurx = (short *)(aline - 0x25a);
  1297.         gcury = (short *)(aline - 0x258);
  1298.         *gcurx = *gcury = 32;    /* magic number -- what MGR uses */
  1299.     }
  1300.  
  1301.     oldvec = syskey->mousevec;
  1302.     oldjvec = syskey->joyvec;    /* jr: save old joystick vector */
  1303.     Initmous(1, parameters, newmvec);
  1304.     syskey->joyvec = (long)newjvec;    /* jr: set up new joystick handler */
  1305.     mousehead = mousetail = 0;
  1306.     return 0;
  1307. }
  1308.  
  1309. static long ARGS_ON_STACK 
  1310. mouse_close(f, pid)
  1311.     FILEPTR *f;
  1312.     int pid;
  1313. {
  1314.     static char parameters[] = {
  1315.         0,         /* Y=0 in lower corner */
  1316.         0,        /* normal button handling */
  1317.         1, 1        /* X, Y scaling factors */
  1318.     };
  1319.  
  1320.     UNUSED(pid);
  1321.     if (!f) return EIHNDL;
  1322.     if (f->links <= 0) {
  1323.         if (!oldvec) {
  1324.             DEBUG(("Mouse not open!!"));
  1325.             return -1;
  1326.         }
  1327.         Initmous(1, parameters, (void *)oldvec);    /* gratuitous (void *) for Lattice */
  1328.         syskey->joyvec = oldjvec;    /* jr: restore old joystick handler */
  1329.         oldvec = 0;
  1330.     }
  1331.     return 0;
  1332. }
  1333.  
  1334. static long ARGS_ON_STACK 
  1335. mouse_read(f, buf, nbytes)
  1336.     FILEPTR *f;
  1337.     char *buf;
  1338.     long nbytes;
  1339. {
  1340.     long count = 0;
  1341.     int mhead;
  1342.     unsigned char *foo;
  1343.  
  1344.     mhead = mousehead;
  1345.     foo = &mousebuf[mhead];
  1346.  
  1347.     if (mhead == mousetail) {
  1348.         if (f->flags & O_NDELAY)
  1349.             return 0;
  1350.         do {
  1351.             yield();
  1352.         } while (mhead == mousetail);
  1353.     }
  1354.  
  1355.     while ( (mhead != mousetail) && (nbytes > 0)) {
  1356.         *buf++ = *foo++;
  1357.         mhead++;
  1358.         if (mhead >= MOUSESIZ) {
  1359.             mhead = 0;
  1360.             foo = mousebuf;
  1361.         }
  1362.         count++;
  1363.         --nbytes;
  1364.     }
  1365.     mousehead = mhead;
  1366.     return count;
  1367. }
  1368.  
  1369. static long ARGS_ON_STACK 
  1370. mouse_ioctl(f, mode, buf)
  1371.     FILEPTR *f;
  1372.     int mode;
  1373.     void *buf;
  1374. {
  1375.     long r;
  1376.  
  1377.     UNUSED(f);
  1378.     if (mode == FIONREAD) {
  1379.         r = mousetail - mousehead;
  1380.         if (r < 0) r += MOUSESIZ;
  1381.         *((long *)buf) = r;
  1382.     }
  1383.     else
  1384.         return EINVFN;
  1385.     return 0;
  1386. }
  1387.  
  1388. static long ARGS_ON_STACK 
  1389. mouse_select(f, p, mode)
  1390.     FILEPTR *f;
  1391.     long p;
  1392.     int mode;
  1393. {
  1394.     UNUSED(f);
  1395.  
  1396.     if (mode != O_RDONLY)
  1397.         return 1;    /* we can always take output :-) */
  1398.  
  1399.     if (mousetail - mousehead)
  1400.         return 1;    /* input waiting already */
  1401.  
  1402.     if (!mousersel)
  1403.         mousersel = p;
  1404.     return 0;
  1405. }
  1406.  
  1407. static void ARGS_ON_STACK 
  1408. mouse_unselect(f, p, mode)
  1409.     FILEPTR *f;
  1410.     long p;
  1411.     int mode;
  1412. {
  1413.     UNUSED(f);
  1414.  
  1415.     if (mode == O_RDONLY && mousersel == p)
  1416.         mousersel = 0;
  1417. }
  1418.  
  1419.  
  1420. /*
  1421.  * UTILITY ROUTINE called by Bconmap() in xbios.c:
  1422.  * this sets handle -1 of process p to a file handle
  1423.  * that has BIOS device "dev". Returns 0 on failure,
  1424.  * non-zero on success.
  1425.  */
  1426.  
  1427. int
  1428. set_auxhandle(p, dev)
  1429.     PROC *p;
  1430.     int dev;
  1431. {
  1432.     FILEPTR *f;
  1433.     struct bios_file *b;
  1434.  
  1435.     f = new_fileptr();
  1436.     if (f) {
  1437.         f->links = 1;
  1438.         f->flags = O_RDWR;
  1439.         f->pos = 0;
  1440.         f->devinfo = 0;
  1441.         f->fc.fs = &bios_filesys;
  1442.         f->fc.aux = dev;
  1443.         f->fc.dev = BIOSDRV;
  1444.         for (b = broot; b; b = b->next) {
  1445.             if (b->private == dev &&
  1446.                 (b->device == &bios_tdevice ||
  1447.                  b->device == &bios_ndevice)) {
  1448.                 f->fc.index = (long)b;
  1449.                 f->dev = b->device;
  1450.                 if (b->device != &fakedev)
  1451.                     f->devinfo = (long)b->tty;
  1452.                 goto found_device;
  1453.             }
  1454.         }
  1455.         f->fc.index = 0;
  1456.         f->dev = &bios_ndevice;
  1457. found_device:
  1458.         if ((*f->dev->open)(f) < 0) {
  1459.             f->links = 0;
  1460.             dispose_fileptr(f);
  1461.             return 0;
  1462.         }
  1463.     } else {
  1464. /* no memory! use the fake FILEPTR we
  1465.  * set up in biosfs_init
  1466.  */
  1467.         f = defaultaux;
  1468.         f->links++;
  1469.     }
  1470.  
  1471.     (void)do_pclose(p, p->aux);
  1472.     p->aux = f;
  1473.  
  1474.     return 1;
  1475. }
  1476.